package org.agent.aigccore.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.agent.aigccore.basic.aop.OpLog;
import org.agent.aigccore.basic.aop.OpsEvent;
import org.agent.aigccore.basic.exception.AuthException;
import org.agent.aigccore.basic.exception.UserException;
import org.agent.aigccore.core.service.user.AuthService;
import org.agent.aigccore.core.service.user.UserService;
import org.agent.aigccore.model.dto.*;
import org.agent.aigccore.model.po.UserInfoPO;
import org.agent.aigccore.model.vo.PageResponse;
import org.agent.aigccore.model.vo.Response;
import org.agent.aigccore.model.vo.TokenVO;
import org.agent.aigccore.model.vo.UserVO;
import org.agent.aigccore.utils.UserConverter;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/api/auth")
@Tag(name = "认证接口", description = "处理用户认证相关操作")
@Slf4j
public class AuthController {
    
    @Resource
    private AuthService authService;
    
    @Resource
    private UserService userService;
    
    /**
     * 用户登录接口
     *
     * @param loginRequest 登录请求参数
     * @return JWT令牌
     */
    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "用户登录接口，成功返回JWT令牌")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "登录成功", content = @Content(schema = @Schema(implementation = Response.class))),
        @ApiResponse(responseCode = "400", description = "登录失败")
    })
    @OpLog(event = OpsEvent.AUTH_LOGIN)
    public ResponseEntity<Response<TokenVO>> login(@RequestBody LoginRequestDTO loginRequest) {
        try {
            String token = authService.login(loginRequest.getUsername(), loginRequest.getPassword(), loginRequest.getRememberMe());
            
            TokenVO tokenVO = new TokenVO(token);
            Response<TokenVO> response = Response.success(tokenVO, "登录成功");
            return ResponseEntity.ok(response);
        } catch (AuthException e) {
            log.error("登录失败, username={}: {}", loginRequest.getUsername(), e.getMessage(), e);
            throw e; // 让全局异常处理器处理
        }
    }
    
    /**
     * 用户注册接口
     *
     * @param userInfoPO 用户信息
     * @return 注册结果
     */
    @PostMapping("/register")
    @Operation(summary = "用户注册", description = "用户注册接口")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "注册成功", content = @Content(schema = @Schema(implementation = Response.class))),
        @ApiResponse(responseCode = "400", description = "注册失败")
    })
    public ResponseEntity<Response<Boolean>> register(@RequestBody UserInfoPO userInfoPO) {
        try {
            boolean result = authService.register(userInfoPO);
            
            Response<Boolean> response = Response.success(
                result,
                result ? "注册成功" : "注册失败"
            );
            
            return ResponseEntity.ok(response);
        } catch (UserException e) {
            log.error("注册失败, username={}, email={}: {}", userInfoPO.getUsername(), userInfoPO.getEmail(), e.getMessage(), e);
            throw e; // 让全局异常处理器处理
        }
    }
    
    /**
     * 修改密码接口
     *
     * @param changePasswordRequest 修改密码请求参数
     * @return 修改结果
     */
    @PostMapping("/change-password")
    @Operation(summary = "修改密码", description = "修改用户密码接口")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "密码修改成功", content = @Content(schema = @Schema(implementation = Response.class))),
        @ApiResponse(responseCode = "400", description = "密码修改失败")
    })
    public ResponseEntity<Response<Boolean>> changePassword(@RequestBody ChangePasswordRequestDTO changePasswordRequest) {
        try {
            boolean result = authService.changePassword(
                changePasswordRequest.getUsername(),
                changePasswordRequest.getOldPassword(),
                changePasswordRequest.getNewPassword()
            );
            
            Response<Boolean> response = Response.success(
                result,
                result ? "密码修改成功" : "密码修改失败"
            );
            
            return ResponseEntity.ok(response);
        } catch (AuthException e) {
            log.error("修改密码失败, username={}: {}", changePasswordRequest.getUsername(), e.getMessage(), e);
            throw e; // 让全局异常处理器处理
        }
    }
    
    /**
     * 获取当前用户信息
     *
     * @return 当前用户信息
     */
    @GetMapping("/me")
    @Operation(summary = "获取当前用户信息", description = "获取当前认证用户的信息")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "获取用户信息成功", content = @Content(schema = @Schema(implementation = Response.class))),
        @ApiResponse(responseCode = "400", description = "获取用户信息失败")
    })
    public ResponseEntity<Response<UserVO>> getCurrentUser() {
        try {
            log.info("开始获取当前用户信息");
            
            // 获取当前认证信息
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            log.info("Authentication对象: {}", authentication);
            
            if (authentication == null) {
                log.warn("Authentication对象为空");
                throw new AuthException("NOT_AUTHENTICATED", "用户未认证");
            }
            
            if (!authentication.isAuthenticated()) {
                log.warn("用户未认证");
                throw new AuthException("NOT_AUTHENTICATED", "用户未认证");
            }
            
            if (authentication.getPrincipal() instanceof String) {
                log.warn("Principal是String类型: {}", authentication.getPrincipal());
                throw new AuthException("NOT_AUTHENTICATED", "用户未认证");
            }
            
            UserVO userVO = null;
            
            // 检查Principal是否为UserInfoPO类型
            if (authentication.getPrincipal() instanceof UserInfoPO userInfoPO) {
                log.info("Principal是UserInfoPO类型");
                // 从Principal中直接获取用户信息
                log.info("从Principal获取的用户信息: {}", userInfoPO);

                userVO = UserConverter.convertToUserVO(userInfoPO);
                log.info("转换后的UserVO: {}", userVO);
            } else {
                log.info("Principal不是UserInfoPO类型，尝试通过用户名查询");
                // 通过用户名查询用户信息
                String username = authentication.getName();
                log.info("当前认证用户名: {}", username);
                
                if (username == null || username.isEmpty()) {
                    log.warn("用户名为空");
                    throw new AuthException("USER_NOT_FOUND", "用户名为空");
                }
                
                UserInfoPO userInfoPO = userService.loadByUsername(username);
                log.info("通过用户名查询到的用户信息: {}", userInfoPO);
                
                if (userInfoPO == null) {
                    log.warn("未找到用户名为{}的用户信息", username);
                    throw new AuthException("USER_NOT_FOUND", "用户信息不存在");
                }
                
                userVO = UserConverter.convertToUserVO(userInfoPO);
                log.info("转换后的UserVO: {}", userVO);
            }
            
            if (userVO == null) {
                log.warn("转换后的UserVO对象为空");
                throw new AuthException("USER_NOT_FOUND", "用户信息不存在");
            }
            
            Response<UserVO> response = Response.success(userVO, "获取用户信息成功");
            log.info("成功获取用户信息，返回结果: {}", response);
            return ResponseEntity.ok(response);
        } catch (AuthException e) {
            log.error("获取用户信息失败: {}", e.getMessage(), e);
            throw e; // 让全局异常处理器处理
        } catch (Exception e) {
            log.error("获取用户信息时发生未预期的错误: {}", e.getMessage(), e);
            throw new AuthException("INTERNAL_ERROR", "内部错误: " + e.getMessage());
        }
    }

    /**
     * 管理员创建用户接口
     *
     * @param userInfoPO 用户信息
     * @return 创建结果
     */
    @PostMapping("/admin/users")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "管理员创建用户", description = "管理员创建用户接口，可指定用户角色")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "创建成功", content = @Content(schema = @Schema(implementation = Response.class))),
        @ApiResponse(responseCode = "400", description = "创建失败")
    })
    @OpLog(event = OpsEvent.USER_CREATE)
    public ResponseEntity<Response<Boolean>> createUser(@RequestBody UserInfoPO userInfoPO) {
        try {
            // 设置用户ID
            userInfoPO.setUserId(java.util.UUID.randomUUID().toString());
            
            // 设置默认状态为正常
            if (userInfoPO.getStatus() == null || userInfoPO.getStatus().trim().isEmpty()) {
                userInfoPO.setStatus("NORMAL");
            }
            
            // 设置创建时间
            Date now = new Date();
            userInfoPO.setGmtCreate(now);
            userInfoPO.setGmtModified(now);
            
            // 插入用户信息
            int result = userService.insert(userInfoPO);
            boolean success = result > 0;
            
            Response<Boolean> response = Response.success(
                success,
                success ? "创建成功" : "创建失败"
            );
            
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            log.error("创建用户失败, username={}, email={}: {}", userInfoPO.getUsername(), userInfoPO.getEmail(), e.getMessage(), e);
            throw new UserException("CREATE_USER_FAILED", "创建用户失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 管理员删除用户
     */
    @DeleteMapping("/admin/users/{userId}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "管理员删除用户", description = "根据 userId 删除用户，仅ADMIN可调用")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "删除成功", content = @Content(schema = @Schema(implementation = Response.class))),
        @ApiResponse(responseCode = "400", description = "删除失败")
    })
    @OpLog(event = OpsEvent.USER_DELETE)
    public ResponseEntity<Response<Boolean>> deleteUser(@PathVariable("userId") String userId) {
        try {
            int affected = userService.delete(userId);
            boolean result = affected > 0;
            
            Response<Boolean> response = Response.success(
                result,
                result ? "删除成功" : "删除失败"
            );
            
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            log.error("删除用户失败, userId={}: {}", userId, e.getMessage(), e);
            throw new UserException("DELETE_USER_FAILED", "删除用户失败: " + e.getMessage(), e);
        }
    }

    /**
     * 管理员修改用户信息
     */
    @PutMapping("/admin/users/{userId}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "管理员修改用户信息", description = "管理员修改用户信息，仅ADMIN可调用")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "修改成功", content = @Content(schema = @Schema(implementation = Response.class))),
        @ApiResponse(responseCode = "400", description = "修改失败")
    })
    @OpLog(event = OpsEvent.USER_UPDATE)
    public ResponseEntity<Response<Boolean>> updateUser(@PathVariable("userId") String userId, @RequestBody UpdateUserRequestDTO updateUserRequest) {
        try {
            // 加载现有用户信息
            UserInfoPO existingUser = userService.load(userId);
            if (existingUser == null) {
                throw new UserException("USER_NOT_FOUND", "用户不存在");
            }
            
            // 只更新非空字段
            if (updateUserRequest.getUsername() != null) {
                existingUser.setUsername(updateUserRequest.getUsername());
            }
            if (updateUserRequest.getEmail() != null) {
                existingUser.setEmail(updateUserRequest.getEmail());
            }
            if (updateUserRequest.getPhone() != null) {
                existingUser.setPhone(updateUserRequest.getPhone());
            }
            if (updateUserRequest.getName() != null) {
                existingUser.setName(updateUserRequest.getName());
            }
            if (updateUserRequest.getIdCard() != null) {
                existingUser.setIdCard(updateUserRequest.getIdCard());
            }
            if (updateUserRequest.getStatus() != null) {
                existingUser.setStatus(updateUserRequest.getStatus());
            }
            if (updateUserRequest.getRole() != null) {
                existingUser.setRole(updateUserRequest.getRole());
            }
            if (updateUserRequest.getLastLoginTime() != null) {
                existingUser.setLastLoginTime(updateUserRequest.getLastLoginTime());
            }
            if (updateUserRequest.getCreator() != null) {
                existingUser.setCreator(updateUserRequest.getCreator());
            }
            if (updateUserRequest.getRemark() != null) {
                existingUser.setRemark(updateUserRequest.getRemark());
            }
            
            // 设置更新时间
            existingUser.setGmtModified(new Date());
            
            // 从认证信息中获取当前用户作为操作人
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.getPrincipal() instanceof UserInfoPO userInfoPO) {
                existingUser.setModifier(userInfoPO.getUsername());
            } else {
                // 如果无法获取用户名，使用默认值
                existingUser.setModifier("SYSTEM");
            }
            
            // 更新用户信息
            int affected = userService.update(existingUser);
            boolean result = affected > 0;
            
            Response<Boolean> response = Response.success(
                result,
                result ? "修改成功" : "修改失败"
            );
            
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            log.error("修改用户信息失败, userId={}: {}", userId, e.getMessage(), e);
            throw new UserException("UPDATE_USER_FAILED", "修改用户信息失败: " + e.getMessage(), e);
        }
    }

    /**
     * 管理员重置用户密码
     */
    @PutMapping("/admin/users/{userId}/password")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "管理员重置用户密码", description = "管理员重置用户密码，仅ADMIN可调用")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "重置成功", content = @Content(schema = @Schema(implementation = Response.class))),
        @ApiResponse(responseCode = "400", description = "重置失败")
    })
    @OpLog(event = OpsEvent.USER_RESET_PASSWORD)
    public ResponseEntity<Response<Boolean>> resetPassword(@PathVariable("userId") String userId, @RequestBody ResetPasswordRequestDTO resetPasswordRequest) {
        try {
            String newPassword = resetPasswordRequest.getNewPassword();
            
            if (newPassword == null || newPassword.isEmpty()) {
                throw new UserException("INVALID_PASSWORD", "新密码不能为空");
            }
            
            // 重置密码
            int affected = userService.resetPassword(userId, newPassword);
            boolean result = affected > 0;
            
            Response<Boolean> response = Response.success(
                result,
                result ? "重置成功" : "重置失败"
            );
            
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            log.error("重置用户密码失败, userId={}: {}", userId, e.getMessage(), e);
            throw new UserException("RESET_PASSWORD_FAILED", "重置用户密码失败: " + e.getMessage(), e);
        }
    }

    /**
     * 管理员分页搜索用户
     */
    @PostMapping("/admin/users/search")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "管理员搜索用户", description = "按用户名/手机号/邮箱关键字分页搜索用户，仅ADMIN可调用")
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "查询成功",
            content = @Content(schema = @Schema(implementation = PageResponse.class)))
    })
    @OpLog(event = OpsEvent.USER_SEARCH)
    public ResponseEntity<PageResponse<UserVO>> searchUsers(@RequestBody UserSearchRequestDTO request) {
        try {
            int page = request.getPage() == null || request.getPage() < 1 ? 1 : request.getPage();
            int size = request.getSize() == null || request.getSize() < 1 ? 10 : request.getSize();
            List<UserInfoPO> list = userService.searchUsers(request.getKeyword(), request.getRole(), request.getStatus(), page, size);
            long total = userService.countSearchUsers(request.getKeyword(), request.getRole(), request.getStatus());
            List<UserVO> voList = new ArrayList<>();
            for (UserInfoPO po : list) {
                voList.add(UserConverter.convertToUserVO(po));
            }
            
            PageResponse<UserVO> response = PageResponse.success(
                voList,
                "查询成功",
                page,
                size,
                total,
                (int) Math.ceil((double) total / size)
            );
            
            return ResponseEntity.ok(response);
        } catch (Exception e) {
            log.error("搜索用户失败: {}", e.getMessage(), e);
            throw new UserException("SEARCH_USERS_FAILED", "搜索用户失败: " + e.getMessage(), e);
        }
    }

}